package com.soulkun.smarthome.ui.splash.register

import android.animation.*
import android.graphics.PorterDuff
import android.text.InputType
import android.text.Selection
import android.view.View
import android.view.animation.AccelerateInterpolator
import android.view.animation.LinearInterpolator
import android.view.animation.OvershootInterpolator
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.soulkun.smarthome.R
import com.soulkun.smarthome.databinding.AppFragmentSplashRegisterBinding
import com.soulkun.smarthome.ui.splash.register.viewmodel.AppSplashRegisterViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import soulkun.library.mvvm.component.BaseDataBindingFragment
import soulkun.library.utils.navigateSafe
import soulkun.library.utils.toast
import soulkun.library.utils.visible

class AppSplashRegisterFragment : BaseDataBindingFragment<AppFragmentSplashRegisterBinding>() {

    private val viewModel by viewModels<AppSplashRegisterViewModel> { defaultViewModelProviderFactory }

    private var shapeAnimatorSet: AnimatorSet? = null
    private var endAnimator: ObjectAnimator? = null
    private var checkAnimator: ObjectAnimator? = null

    override fun setLayout(): Int {
        return R.layout.app_fragment_splash_register
    }

    override fun initView() {
        requireDataBinding().pbSplashRegisterProgress.indeterminateDrawable.setColorFilter(
            resources.getColor(
                R.color.app_orange_00
            ), PorterDuff.Mode.MULTIPLY
        )
        requireDataBinding().pbSplashRegisterProgress.interpolator = LinearInterpolator()
    }

    override fun initData() {
        requireDataBinding().lifecycleOwner = viewLifecycleOwner
        requireDataBinding().viewModel = viewModel
        requireDataBinding().onClickListener = View.OnClickListener {
            when (it.id) {
                R.id.btn_splash_register_register -> {
                    startRegisterAnimation()
                    viewModel.register(
                        viewModel.usernameEditLiveData.value!!,
                        viewModel.passwordEditLiveData.value!!
                    ).observe(viewLifecycleOwner) { result ->
                        stopRegisterAnimation()
                        val result = result.getOrNull()
                        if (result != null) {
                            result.statusMessage.toast()
                            findNavController().navigateUp()
                        }else{
                            restoreRegisterAnimation()
                        }
                    }
                }
                R.id.iv_splash_register_input_icon_password_visibility -> {
                    if (viewModel.passwordVisibility) {
                        requireDataBinding().etSplashRegisterInputTextPassword.inputType =
                            InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
                        Selection.setSelection(
                            requireDataBinding().etSplashRegisterInputTextPassword.text,
                            viewModel.passwordEditLiveData.value?.length ?: 0
                        )
                        requireDataBinding().ivSplashRegisterInputIconPasswordVisibility.setImageDrawable(
                            ResourcesCompat.getDrawable(
                                resources,
                                R.drawable.app_splash_register_icon_invisible,
                                null
                            )
                        )
                    } else {
                        requireDataBinding().etSplashRegisterInputTextPassword.inputType =
                            InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
                        Selection.setSelection(
                            requireDataBinding().etSplashRegisterInputTextPassword.text,
                            viewModel.passwordEditLiveData.value?.length ?: 0
                        )
                        requireDataBinding().ivSplashRegisterInputIconPasswordVisibility.setImageDrawable(
                            ResourcesCompat.getDrawable(
                                resources,
                                R.drawable.app_splash_register_icon_visible,
                                null
                            )
                        )
                    }
                    viewModel.passwordVisibility = !viewModel.passwordVisibility
                }
                R.id.iv_splash_register_input_icon_username_checked -> {
                    if (!viewModel.usernameChecked) {
                        startCheckAnimation()
                        viewModel.usernameChecked = true
                        viewModel.checkUserName(viewModel.usernameEditLiveData.value!!)
                            .observe(viewLifecycleOwner) { result ->
                                stopCheckAnimation(result.getOrNull() != null)
                            }
                    }
                }
                R.id.iv_splash_register_input_icon_password_delete -> {
                    viewModel.passwordEditLiveData.value = ""
                }
                R.id.iv_splash_register_input_icon_username_delete -> {
                    viewModel.usernameEditLiveData.value = ""
                }
                R.id.iv_splash_register_icon_back -> {
                    findNavController().navigateUp()
                }
            }
        }
    }

    override fun initListener() {
        viewModel.usernameEditLiveData.observe(viewLifecycleOwner) {
            if (viewModel.usernameChecked) {
                requireDataBinding().ivSplashRegisterInputIconUsernameChecked.setImageDrawable(
                    ResourcesCompat.getDrawable(
                        resources,
                        R.drawable.app_splash_register_icon_username_unchecked,
                        null
                    )
                )
                viewModel.usernameChecked = false
            }
        }
    }

    override fun doOnCreate() {
    }

    private fun startRegisterAnimation() {
        requireDataBinding().pbSplashRegisterProgress.visible(false)
        shapeAnimatorSet = AnimatorSet()
        val currentWidth = requireDataBinding().clSplashRegisterInput.measuredWidth.toFloat()
        val currentHeight = requireDataBinding().clSplashRegisterInput.measuredHeight.toFloat()
        val alphaAnimator = ObjectAnimator.ofFloat(
            requireDataBinding().clSplashRegisterInputContainer,
            "alpha",
            1f,
            0f
        )
        val scaleXAnimator = ObjectAnimator.ofFloat(
            requireDataBinding().clSplashRegisterInput,
            "scaleX",
            1f,
            (currentHeight / currentWidth)
        )
        alphaAnimator.duration = 200
        scaleXAnimator.duration = 500
        shapeAnimatorSet?.playTogether(alphaAnimator, scaleXAnimator)
        shapeAnimatorSet?.interpolator = AccelerateInterpolator()
        shapeAnimatorSet?.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator?) {
            }

            override fun onAnimationEnd(animation: Animator?) {
                requireDataBinding().pbSplashRegisterProgress.visible(true)
                val scaleXAnimator = PropertyValuesHolder.ofFloat("scaleX", 0f, 1f)
                val scaleYAnimator = PropertyValuesHolder.ofFloat("scaleY", 0f, 1f)
                endAnimator = ObjectAnimator.ofPropertyValuesHolder(
                    requireDataBinding().pbSplashRegisterProgress,
                    scaleXAnimator,
                    scaleYAnimator
                )
                endAnimator?.duration = 1000
                endAnimator?.interpolator = OvershootInterpolator()
                endAnimator?.start()
            }

            override fun onAnimationCancel(animation: Animator?) {
            }

            override fun onAnimationRepeat(animation: Animator?) {
            }

        })
        shapeAnimatorSet?.start()
    }

    private fun stopRegisterAnimation() {
        shapeAnimatorSet?.pause()
        shapeAnimatorSet?.cancel()
        shapeAnimatorSet = null
        endAnimator?.pause()
        endAnimator?.cancel()
        endAnimator = null
        requireDataBinding().pbSplashRegisterProgress.visible(false)
    }

    private fun restoreRegisterAnimation() {
        val restoreAnimatorSet = AnimatorSet()
        val alphaAnimator = ObjectAnimator.ofFloat(
            requireDataBinding().clSplashRegisterInputContainer,
            "alpha",
            0f,
            1f
        )
        val scaleXAnimator = ObjectAnimator.ofFloat(
            requireDataBinding().clSplashRegisterInput,
            "scaleX",
            1f
        )
        alphaAnimator.duration = 200
        scaleXAnimator.duration = 500
        restoreAnimatorSet.playTogether(alphaAnimator, scaleXAnimator)
        restoreAnimatorSet.interpolator = AccelerateInterpolator()
        restoreAnimatorSet.start()
    }

    private fun startCheckAnimation() {
        requireDataBinding().ivSplashRegisterInputIconUsernameChecked.setImageDrawable(
            ResourcesCompat.getDrawable(
                resources,
                R.drawable.app_splash_register_progress_username_checked_loading,
                null
            )
        )
        checkAnimator = ObjectAnimator.ofFloat(
            requireDataBinding().ivSplashRegisterInputIconUsernameChecked,
            "rotation",
            0f,
            360f
        )
        checkAnimator?.duration = 2000
        checkAnimator?.repeatCount = ObjectAnimator.INFINITE
        checkAnimator?.interpolator = LinearInterpolator()
        checkAnimator?.start()
    }

    private fun stopCheckAnimation(availability: Boolean) {
        checkAnimator?.pause()
        checkAnimator?.cancel()
        if (availability) {
            requireDataBinding().ivSplashRegisterInputIconUsernameChecked.setImageDrawable(
                ResourcesCompat.getDrawable(
                    resources,
                    R.drawable.app_splash_register_icon_username_checked_ok,
                    null
                )
            )
        } else {
            requireDataBinding().ivSplashRegisterInputIconUsernameChecked.setImageDrawable(
                ResourcesCompat.getDrawable(
                    resources,
                    R.drawable.app_splash_register_icon_username_checked_wrong,
                    null
                )
            )
        }
        requireDataBinding().ivSplashRegisterInputIconUsernameChecked.rotation = 0f
    }

    override fun onDestroyView() {
        super.onDestroyView()
        shapeAnimatorSet?.cancel()
        shapeAnimatorSet = null
        endAnimator?.cancel()
        endAnimator = null
        checkAnimator?.cancel()
        checkAnimator = null
    }

}